package de.idgard.android.addon.ui.services.impl;

import org.apache.http.cookie.Cookie;
import org.apache.http.impl.cookie.BasicClientCookie;

import android.net.http.SslCertificate.DName;
import android.webkit.CookieManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import de.idgard.android.R;
import de.idgard.android.addon.services.GlobalServiceRegistry;
import de.idgard.android.addon.ui.services.AddonStateService;
import de.idgard.android.addon.ui.services.BrowserUtilityService;
import de.idgard.android.addon.ui.services.PropertiesService;
import de.idgard.android.addon.ui.services.ZircoToIDGardAPI;
import de.idgard.android.addon.ui.services.dto.FieldDTO;
import de.idgard.android.addon.ui.services.dto.IDGardCookieDTO;

/**
 * 
 * @author ckaratza
 * 
 */

class BrowserUtilityServiceImpl implements BrowserUtilityService {

	ZircoToIDGardAPI api;

	public void setZircoToIDGardAPI(ZircoToIDGardAPI api) {
		this.api = api;
	}

	private AddonStateService addonStateService;
	private Cookie[] cookies;

	public void setAddonStateService(AddonStateService addonStateService) {
		this.addonStateService = addonStateService;
	}

	private PropertiesService propertiesService;

	public void setPropertiesService(PropertiesService propertiesService) {
		this.propertiesService = propertiesService;
	}

	private IDGardCookieDTO cookieDTO = new IDGardCookieDTO(null, null, null);

	private String originalBrowserUserAgentString;
	private String cachedUserAgentString;

	private String getOriginalBrowserUserAgentString(WebSettings settings) {
		if (originalBrowserUserAgentString == null) {
			originalBrowserUserAgentString = settings.getUserAgentString();
		}
		return originalBrowserUserAgentString;
	}

	private String generateUserAgentString(final String currentUserAgentString) {
		String authTemplate = propertiesService.getString(R.string.authenticationtemplate);
		String authenticationPart = "";
		if (cookieDTO.getIdgardId() != null) {
			authenticationPart = authTemplate.replace("${IDG}", cookieDTO.getIdgardId());
			int indexOfAuthPart = currentUserAgentString.indexOf("=!=");
			if (currentUserAgentString.indexOf("=!=") != -1) {
				return currentUserAgentString.substring(0, indexOfAuthPart) + authenticationPart;
			}
		}
		return currentUserAgentString + authenticationPart;
	}

	@Override
	public String provisionUserAgentString(WebView wview) {
		WebSettings settings = wview.getSettings();
		String authenticatedUserAgentString = generateUserAgentString(getOriginalBrowserUserAgentString(settings));
		settings.setUserAgentString(authenticatedUserAgentString);
		this.cachedUserAgentString = authenticatedUserAgentString;
		if (GlobalServiceRegistry.instance().getProxyService().getCommunicatorsAuthenticationString() == null) {
			GlobalServiceRegistry.instance().getProxyService().setCommunicatorsAuthenticationString(cachedUserAgentString);
		}
		return authenticatedUserAgentString;
	}

	private String extractCookiePart(String cookie, int partId) {
		String partIndicator = propertiesService.getString(partId);
		int partIndex = cookie.indexOf(partIndicator) + partIndicator.length() + 1;
		int partEnd = cookie.indexOf(";", partIndex);
		if (partEnd < 0) {
			partEnd = cookie.length();
		}
		return cookie.substring(partIndex, partEnd);
	}

	@Override
	public IDGardCookieDTO extractIDGardCookieData(final String url) {
		String cookie = CookieManager.getInstance().getCookie(url);
		if (!(cookie == null && !this.checkIfIDGardLoginUrl(url)) && !this.isCookieValid(cookie)) {
			return null;
		}
		if (cookie != null && !addonStateService.isAddonON()) {
			cookieDTO.setIdgardId(extractCookiePart(cookie, R.string.idgardidcookie));
			cookieDTO.setJsessionId(extractCookiePart(cookie, R.string.jsessionidcookie));
		}
		setIDGardData(cookieDTO);
		return cookieDTO;

	}

	private Cookie createCookie(String name, String value) {
		BasicClientCookie cookie = new BasicClientCookie(name, value);
		cookie.setVersion(0);
		cookie.setDomain(propertiesService.getString(R.string.system_domain));
		cookie.setPath("/");

		return cookie;
	}

	public boolean isCookieValid(String cookie) {
		if (cookie == null || !cookie.contains(propertiesService.getString(R.string.idgardidcookie))) {
			return false;
		}
		return true;
	}

	@Override
	public String getIDGardServerUrl() {
		return propertiesService.getString(R.string.system_url);
	}

	@Override
	public boolean checkIfIDGardLoginUrl(String url) {
		return getIDGardServerUrl().equals(url) || propertiesService.getString(R.string.system_url_alternative).equals(url) || url.startsWith(getIDGardServerUrl())
				|| (url != null && url.startsWith(propertiesService.getString(R.string.system_url_alternative)));
	}

	@Override
	public void invalidateIDGardONModeCookies() {
		CookieManager.getInstance().removeAllCookie();
		cookieDTO.setIdgardId(null);
		cookieDTO.setJsessionId(null);
	}

	@Override
	public IDGardCookieDTO getIDGardData() {
		return cookieDTO;
	}

	@Override
	public void setIDGardData(IDGardCookieDTO dto) {
		this.cookieDTO = dto;

		cookies = new Cookie[2];
		cookies[0] = createCookie(propertiesService.getString(R.string.idgardidcookie), cookieDTO.getIdgardId());
		cookies[1] = createCookie(propertiesService.getString(R.string.jsessionidcookie), cookieDTO.getJsessionId());
	}

	@Override
	public Cookie[] getIdgardCookies() {
		return cookies;
	}

	@Override
	public boolean checkIfCertificateIssuerIsUniscon(DName dname) {
		return (propertiesService.getString(R.string.cname).equals(dname.getCName()) && propertiesService.getString(R.string.dname).equals(dname.getDName())
				&& propertiesService.getString(R.string.oname).equals(dname.getOName()) && propertiesService.getString(R.string.uname).equals(dname.getUName()));
	}

	private String getUserAgentSeparator() {
		return propertiesService.getString(R.string.useragentseparator);
	}

	@Override
	public String updateWebViewUserAgentStringWithProfileInfo(final String profileToken, FieldDTO... miscFields) {
		StringBuilder sb = new StringBuilder();
		String separator = getUserAgentSeparator();
		WebSettings settings = api.getContainersCurrentView().getSettings();
		String current = settings.getUserAgentString();
		if (current != null) {
			String[] splitted = current.split(separator);
			sb.append(splitted[0]).append(separator).append(splitted[1]).append(separator).append(profileToken);
			if (miscFields != null) {
				for (FieldDTO field : miscFields) {
					sb.append(separator).append(field);
				}
			}
			settings.setUserAgentString(sb.toString());
		}
		this.cachedUserAgentString = settings.getUserAgentString();

		GlobalServiceRegistry.instance().getProxyService().setCommunicatorsAuthenticationString(cachedUserAgentString);

		return cachedUserAgentString;
	}

	public String getCachedUserAgentString() {
		return cachedUserAgentString;
	}

	@Override
	public boolean removeProfileInfoFromWebViewUserAgentString() {
		boolean wasActuallyRemoved = true;
		StringBuilder sb = new StringBuilder();
		String separator = getUserAgentSeparator();
		WebSettings settings = api.getContainersCurrentView().getSettings();
		String current = settings.getUserAgentString();
		if (current != null) {
			String[] splitted = current.split(separator);
			if (splitted.length == 2) {
				wasActuallyRemoved = false;
			}
			sb.append(splitted[0]).append(separator).append(splitted[1]);
			settings.setUserAgentString(sb.toString());
		}
		return wasActuallyRemoved;
	}

	@Override
	public boolean checkIfIDGardDomainOrigination(String url) {
		if (url == null) {
			return false;
		}
		return url.contains(propertiesService.getString(R.string.system_domain));
	}

	@Override
	public boolean checkIfOpenLoginPageWithWebApp() {
		return propertiesService.getString(R.string.openloginMode).equals("idgard_webapp");
	}

	@Override
	public boolean checkIfIDStartPage(String url) {
		return propertiesService.getString(R.string.aboutstart).equals(url) || propertiesService.getString(R.string.assetPage).equals(url);
	}

	@Override
	/**
	 * Dangerous handling
	 */
	public String getUserAgentStringOfCurrentView() {
		return cachedUserAgentString;
		// return getContainersCurrentView().getSettings().getUserAgentString();
	}
}
